﻿/*
* Varint.h
*/

#ifndef __GDK_VARINT_H__
#define __GDK_VARINT_H__

#include <gdk/core/Types.h>
#include <gdk/core/Exception.h>
#include <vector>
#include <list>
#include <set>


namespace gdk
{

	//当 ssize_t 定义为 long 时, 增加下面代码
#if defined(_M_X64) || defined(__x86_64__) || defined(__IOS__) || defined(_WIN32)// || defined(__ANDROID__)
#	define DECLARE_VARINT_T(Varint_T) \
	public:\
		__INLINE__ Varint_T  (int n)                  { _number = n; }\
		__INLINE__ Varint_T  operator + (int n) const { return Varint_T(this->_number + n); }\
		__INLINE__ Varint_T  operator - (int n) const { return Varint_T(this->_number - n); }\
		__INLINE__ Varint_T  operator * (int n) const { return Varint_T(this->_number * n); }\
		__INLINE__ Varint_T  operator / (int n) const { return Varint_T(this->_number / n); }\
		__INLINE__ Varint_T  operator % (int n) const { return Varint_T(this->_number % n); }\
		__INLINE__ Varint_T  operator & (int n) const { return Varint_T(this->_number & n); }\
		__INLINE__ Varint_T  operator | (int n) const { return Varint_T(this->_number | n); }\
		__INLINE__ Varint_T  operator ^ (int n) const { return Varint_T(this->_number ^ n); }\
		__INLINE__ Varint_T& operator +=(int n)       { this->_number += n; return *this; }\
		__INLINE__ Varint_T& operator -=(int n)       { this->_number -= n; return *this; }\
		__INLINE__ Varint_T& operator *=(int n)       { this->_number *= n; return *this; }\
		__INLINE__ Varint_T& operator /=(int n)       { this->_number /= n; return *this; }\
		__INLINE__ Varint_T& operator %=(int n)       { this->_number %= n; return *this; }\
		__INLINE__ Varint_T& operator &=(int n)       { this->_number &= n; return *this; }\
		__INLINE__ Varint_T& operator |=(int n)       { this->_number |= n; return *this; }\
		__INLINE__ Varint_T& operator ^=(int n)       { this->_number ^= n; return *this; }\
		__INLINE__ bool      operator ==(int n) const { return this->_number == n; }\
		__INLINE__ bool      operator !=(int n) const { return this->_number != n; }\
		__INLINE__ bool      operator > (int n) const { return this->_number >  n; }\
		__INLINE__ bool      operator < (int n) const { return this->_number <  n; }\
		__INLINE__ bool      operator >=(int n) const { return this->_number >= n; }\
		__INLINE__ bool      operator <=(int n) const { return this->_number <= n; }
#else
#	define DECLARE_VARINT_T(Varint_T)
#endif


#define VARINT_T(Varint_T, Tyval, UTyval) \
	class Varint_T\
	{\
		DECLARE_VARINT_T(Varint_T)\
	private:\
		Tyval	_number;\
		\
	public:\
		__INLINE__ Varint_T(void)              { _number = 0; }\
		__INLINE__ Varint_T(Tyval n)           { _number = n; }\
		__INLINE__ Varint_T(const Varint_T &v) { _number = v._number; }\
		\
		__INLINE__           operator Tyval()               const { return _number; }\
		__INLINE__ Varint_T& operator ++()                        { ++this->_number; return *this; }\
		__INLINE__ Varint_T& operator --()                        { --this->_number; return *this; }\
		__INLINE__ Varint_T  operator ++(int)                     { Varint_T tmp(*this); ++this->_number; return tmp; }\
		__INLINE__ Varint_T  operator --(int)                     { Varint_T tmp(*this); --this->_number; return tmp; }\
		__INLINE__ Varint_T  operator + (const Varint_T &v) const { return Varint_T(this->_number + v._number); }\
		__INLINE__ Varint_T  operator - (const Varint_T &v) const { return Varint_T(this->_number - v._number); }\
		__INLINE__ Varint_T  operator * (const Varint_T &v) const { return Varint_T(this->_number * v._number); }\
		__INLINE__ Varint_T  operator / (const Varint_T &v) const { return Varint_T(this->_number / v._number); }\
		__INLINE__ Varint_T  operator % (const Varint_T &v) const { return Varint_T(this->_number % v._number); }\
		__INLINE__ Varint_T  operator & (const Varint_T &v) const { return Varint_T(this->_number & v._number); }\
		__INLINE__ Varint_T  operator | (const Varint_T &v) const { return Varint_T(this->_number | v._number); }\
		__INLINE__ Varint_T  operator ^ (const Varint_T &v) const { return Varint_T(this->_number ^ v._number); }\
		__INLINE__ Varint_T& operator +=(const Varint_T &v)       { this->_number += v._number; return *this; }\
		__INLINE__ Varint_T& operator -=(const Varint_T &v)       { this->_number -= v._number; return *this; }\
		__INLINE__ Varint_T& operator *=(const Varint_T &v)       { this->_number *= v._number; return *this; }\
		__INLINE__ Varint_T& operator /=(const Varint_T &v)       { this->_number /= v._number; return *this; }\
		__INLINE__ Varint_T& operator %=(const Varint_T &v)       { this->_number %= v._number; return *this; }\
		__INLINE__ Varint_T& operator &=(const Varint_T &v)       { this->_number &= v._number; return *this; }\
		__INLINE__ Varint_T& operator |=(const Varint_T &v)       { this->_number |= v._number; return *this; }\
		__INLINE__ Varint_T& operator ^=(const Varint_T &v)       { this->_number ^= v._number; return *this; }\
		__INLINE__ bool      operator ==(const Varint_T &v) const { return this->_number == v._number; }\
		__INLINE__ bool      operator !=(const Varint_T &v) const { return this->_number != v._number; }\
		__INLINE__ bool      operator > (const Varint_T &v) const { return this->_number >  v._number; }\
		__INLINE__ bool      operator < (const Varint_T &v) const { return this->_number <  v._number; }\
		__INLINE__ bool      operator >=(const Varint_T &v) const { return this->_number >= v._number; }\
		__INLINE__ bool      operator <=(const Varint_T &v) const { return this->_number <= v._number; }\
		\
		__INLINE__ Varint_T  operator + (Tyval n) const { return Varint_T(this->_number + n); }\
		__INLINE__ Varint_T  operator - (Tyval n) const { return Varint_T(this->_number - n); }\
		__INLINE__ Varint_T  operator * (Tyval n) const { return Varint_T(this->_number * n); }\
		__INLINE__ Varint_T  operator / (Tyval n) const { return Varint_T(this->_number / n); }\
		__INLINE__ Varint_T  operator % (Tyval n) const { return Varint_T(this->_number % n); }\
		__INLINE__ Varint_T  operator & (Tyval n) const { return Varint_T(this->_number & n); }\
		__INLINE__ Varint_T  operator | (Tyval n) const { return Varint_T(this->_number | n); }\
		__INLINE__ Varint_T  operator ^ (Tyval n) const { return Varint_T(this->_number ^ n); }\
		__INLINE__ Varint_T& operator +=(Tyval n)       { this->_number += n; return *this; }\
		__INLINE__ Varint_T& operator -=(Tyval n)       { this->_number -= n; return *this; }\
		__INLINE__ Varint_T& operator *=(Tyval n)       { this->_number *= n; return *this; }\
		__INLINE__ Varint_T& operator /=(Tyval n)       { this->_number /= n; return *this; }\
		__INLINE__ Varint_T& operator %=(Tyval n)       { this->_number %= n; return *this; }\
		__INLINE__ Varint_T& operator &=(Tyval n)       { this->_number &= n; return *this; }\
		__INLINE__ Varint_T& operator |=(Tyval n)       { this->_number |= n; return *this; }\
		__INLINE__ Varint_T& operator ^=(Tyval n)       { this->_number ^= n; return *this; }\
		__INLINE__ bool      operator ==(Tyval n) const { return this->_number == n; }\
		__INLINE__ bool      operator !=(Tyval n) const { return this->_number != n; }\
		__INLINE__ bool      operator > (Tyval n) const { return this->_number >  n; }\
		__INLINE__ bool      operator < (Tyval n) const { return this->_number <  n; }\
		__INLINE__ bool      operator >=(Tyval n) const { return this->_number >= n; }\
		__INLINE__ bool      operator <=(Tyval n) const { return this->_number <= n; }\
		\
		/* 与序列化运算符号操作冲突
		__INLINE__ Varint_T  operator << (int i) const   { return Varint_T(this->_number << i); }\
		__INLINE__ Varint_T  operator >> (int i) const   { return Varint_T(this->_number >> i); }\
		*/\
		__INLINE__ Varint_T& operator <<=(int i)         { this->_number <<= i; return *this; }\
		__INLINE__ Varint_T& operator >>=(int i)         { this->_number >>= i; return *this; }\
		\
		template<typename Ty> __INLINE__ explicit Varint_T(Ty n) { _number = static_cast<Tyval>(n); }\
		template<typename Ty> __INLINE__ Ty cast(void) const     { return static_cast<Ty>(_number); }\
		\
	public:\
		template<typename Tyis> friend Tyis& operator >>(Tyis &is, Varint_T &v) __THROW1;\
		template<typename Tyos> friend Tyos& operator <<(Tyos &os, const Varint_T &v) __THROW1;\
	};\
	typedef std::vector<Varint_T> Varint_T##Array;\
	typedef std::list<Varint_T> Varint_T##List;\
	typedef std::set<Varint_T> Varint_T##Set;\
	\
	template<typename Tyis>\
	Tyis& operator >>(Tyis &is, Varint_T &v) __THROW1\
	{\
		uint8_t b;\
		UTyval n = 0;\
		int count = 0;\
		\
		for (;;) {\
			is >> b;\
			n |= static_cast<UTyval>(b & 0x7F) << (7 * count);\
			if (!(b & 0x80)) break;\
			\
			if (++count >= static_cast<int>((sizeof(Tyval) * 8 + 6) / 7)) {\
				__THROW__(__TEXT__("Tyis& operator >>(Tyis &is, Varint_T &v)"));\
			}\
		}\
		v._number = (n >> 1) ^ -static_cast<Tyval>(n & 1);\
		\
		return is;\
	}\
	template<typename Tyos>\
	Tyos& operator <<(Tyos &os, const Varint_T &v) __THROW1\
	{\
		uint8_t bytes[(sizeof(Tyval) * 8 + 6) / 7];\
		int size = 0;\
		UTyval n = (v._number << 1) ^ (v._number >> (sizeof(Tyval) * 8 - 1));\
		while (n > 0x7F)\
		{\
			bytes[size++] = (static_cast<uint8_t>(n) & 0x7F) | 0x80;\
			n >>= 7;\
		}\
		bytes[size++] = static_cast<uint8_t>(n) & 0x7F;\
		\
		if (size != os.write(bytes, size))\
			__THROW__(__TEXT__("Tyos& operator <<(Tyos &os, const Varint_T &v)"));\
		\
		return os;\
	}


	VARINT_T(Varint, ssize_t, size_t)
	VARINT_T(Varint64, int64_t, uint64_t)



}//namespace gdk


#endif //__GDK_VARINT_H__
